package com.ftwj.demo.utils.file;

import org.springframework.web.multipart.MultipartFile;

import com.ftwj.demo.utils.logs.LoggerUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
*
* <p>Title: FileUpAndDownUtils</p>  
* <p>Description: 描述：文件上传下载工具类，推荐当文件大小超过50M时使用Buffer缓冲上传下载， 具体视带宽和磁盘读写速度而定</p> TODO 分片上传，断点续传
* <p>Copyright: Copyright (c) 2020 </p>  
* <p>Company: 兰州飞天网景信息产业有限公司</p>    
* @author WangSLi
* @date 2020年4月21日 上午11:59:34
* @version V1.0
 */
public class FileUpAndDownUtils {

	private static final int FIle_BUFFER_SIZE=1024*10;
 
    /**
     * <p>Description: 普通文件上传</p>  
     * @param file  MultipartFile
     * @param path    
     * @author HeYang
     * @date 2020年4月17日  
     * @version 1.0
     */
	public static void uploadFile(MultipartFile file, String path) throws RuntimeException {
		File save = new File(path);
		File parentFile = save.getParentFile();
		if (!parentFile.exists()) {
			parentFile.mkdirs();
		}
		try {
			file.transferTo(save); //保存文件
		} catch (FileNotFoundException e) {
			LoggerUtil.error("文件保存失败", e);
			// 这里抛出RuntimeException,实际时抛出自定义异常,方便在上一层捕捉自定义异常,对异常信息统一管理,并返会前台
			throw new RuntimeException("文件读取异常");
		} catch (IOException e) {
			LoggerUtil.error("上传文件IO异常", e);
			throw new RuntimeException("文件读取异常");
		}
	}
	
	/**
	 * <p>Description: 缓冲流上传文件</p>  
	 * @param file
	 * @param path
	 * @date 2020年4月17日  
	 * @version 1.0
	 */
	public static void uploadFileBuffer(MultipartFile file, String path) throws RuntimeException {
		File save = new File(path);
		File parentFile = save.getParentFile();
		if (!parentFile.exists()) {
			parentFile.mkdirs();
		}
		try (
			// 缓存流	
			BufferedInputStream bin = new BufferedInputStream(file.getInputStream());// 输入流缓存流
			BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(save));// 输出流缓存流	
		){
			byte[] b = new byte[FIle_BUFFER_SIZE];// 缓存数组
			int len = 0;
			while ((len = bin.read(b)) != -1) {
				bout.write(b, 0, len);
				bout.flush();
			}
		} catch (FileNotFoundException e) {
			LoggerUtil.error("文件保存失败", e);
			// 这里抛出RuntimeException,实际时抛出自定义异常,方便在上一层捕捉自定义异常,对异常信息统一管理,并返会前台
			throw new RuntimeException("文件读取异常");
		} catch (IOException e) {
			LoggerUtil.error("上传文件IO异常", e);
			throw new RuntimeException("文件读取异常");
		}
	}


	/**
	 * <p>Title: downloadFile</p>  
	 * <p>Description: 下载文件</p>  
	 * @param request
	 * @param response
	 * @param path   带文件名的全路径
	 * @param name   文件名
	 * @author HeYang
	 * @date 2020年4月20日  
	 * @version 1.0
	 */
	public static void downloadFile(HttpServletRequest request, HttpServletResponse response, String path, String name) throws RuntimeException {
		File file = new File(path);
		if (!file.exists()) {
			LoggerUtil.info("文件不存在");
			throw new RuntimeException("文件不存在");
		}
		try (
			// 缓存流
			BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
			BufferedOutputStream bout = new BufferedOutputStream(response.getOutputStream());	
		){
			//设置请求头
			String fileName =setFileDownloadHeader(request,name);
			response.setContentType("application/x-download");
			response.addHeader("content-type", "application/x-download;charset=utf-8");
			response.setHeader("Accept-Ranges", "bytes");
			response.setHeader("Content-Length", file.length() + "");
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
			byte[] b = new byte[1024 * 5];// 缓存数组
			int len = 0;
			while ((len = bin.read(b)) != -1) {
				bout.write(b, 0, len);
				bout.flush();
			}
		} catch (IOException e) {
			LoggerUtil.error("上传文件IO异常", e);
			throw new RuntimeException("文件读取异常");
		} 
	}
    
    public String downLoadFile(HttpServletResponse response, String path, String name) {
		response.setCharacterEncoding("UTF-8");
		File f = new File(path);
		if (!f.exists()) {
			LoggerUtil.info("文件不存在");
			throw new  RuntimeException("文件不存在");
		}
		try (
			InputStream fis = new BufferedInputStream(new FileInputStream(path));
			OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
		){
			byte[] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();
			response.reset();
			response.addHeader("content-type","application/octet-stream;charset=UTF-8");
			response.addHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(name, "UTF-8"));
			toClient.write(buffer);
			toClient.flush();
			toClient.close();
		} catch (IOException e) {
			LoggerUtil.error("文件下载IO异常", e);
			throw new RuntimeException("文件读取异常");
		} 
		return "SUCCESS";
	}
    
    /**
     * <p>Title: setFileDownloadHeader</p>  
     * <p>Description: 不同浏览器下载文件时，设置文件名</p>  
     * @param request
     * @param fileName
     * @author HeYang
     * @date 2020年4月20日  
     * @version 1.0
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException{
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE")){
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }
        else if (agent.contains("Firefox")){
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }
        else if (agent.contains("Chrome")){
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        else{
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
    
}

